package com.linkwechat.common.tenant;

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.core.parser.ISqlParserFilter;
import com.baomidou.mybatisplus.core.parser.SqlInfo;
import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.apache.ibatis.executor.statement.CallableStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.util.Iterator;
import java.util.List;

/**
 * 注意点 SqlParserFilter的doFilter方法中，如果使用MetaObject类的getId方法去判断该方法是过滤还是放行的时候、对比的方法必须是Mapper方法，因为MetaObject的getId方法得到的都是Mapper层的方法
 * 尝试扩展到service层
 */
@Intercepts({@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class, Integer.class}
)})
public class CustomerPaginationInterceptor extends PaginationInterceptor {
    private List<ISqlParser> sqlParserList;
    private ISqlParserFilter sqlParserFilter;
    @Override
    protected void sqlParser(MetaObject metaObject) {
        if (null != metaObject) {
            Object originalObject = metaObject.getOriginalObject();
            StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(originalObject);
            metaObject = SystemMetaObject.forObject(statementHandler);
            //1、这一句就是SqlParserFilter的作用、如果SqlParserFilter不等于空、并且执行SqlParserFilter接口的doFilter
            // 方法的到的结果值为 true 的话就不往下执行了
            if (null != this.sqlParserFilter && this.sqlParserFilter.doFilter(metaObject)) {
                return;
            }
            //2、这个是用于@SqlParser注解的、如果@SqlParser注解值为 true 则不往下执行、这个是放在Mapper接口上的
            if (SqlParserHelper.getSqlParserInfo(metaObject)) {
                return;
            }

            //3、这里开始进行SQL解析  sqlParserList是解析链
            if (CollectionUtils.isNotEmpty(this.sqlParserList)) {
                statementHandler = metaObject.hasGetter("delegate") ? (StatementHandler)metaObject.getValue("delegate") : statementHandler;
                if (!(statementHandler instanceof CallableStatementHandler)) {
                    boolean sqlChangedFlag = false;//标记是否修改过Sql
                    String originalSql = (String)metaObject.getValue("delegate.boundSql.sql");
                    Iterator var6 = this.sqlParserList.iterator();
                    //循环解析了
                    while(var6.hasNext()) {
                        ISqlParser sqlParser = (ISqlParser)var6.next();
                        if (sqlParser.doFilter(metaObject, originalSql)) {
                            SqlInfo sqlInfo = sqlParser.parser(metaObject, originalSql);
                            if (null != sqlInfo) {
                                originalSql = sqlInfo.getSql();
                                sqlChangedFlag = true;
                            }
                        }
                    }

                    if (sqlChangedFlag) {
                        metaObject.setValue("delegate.boundSql.sql", originalSql);
                    }
                }
            }
        }

    }
}
